package fr.univnantes.lina.uima.connectors.ftb;

/** 
 * UIMA Connectors
 * Copyright (C) 2010  Nicolas Hernandez
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_component.AnalysisComponent;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceInitializationException;
import fr.univnantes.lina.uima.common.AnnotationUtils;
import fr.univnantes.lina.uima.common.CommonAE;
import fr.univnantes.lina.uima.common.JCasSofaViewUtils;
import fr.univnantes.lina.uima.connectors.types.XMLAttributeAnnotation;
import fr.univnantes.lina.uima.connectors.types.XMLElementAnnotation;
import fr.univnantes.lina.uima.connectors.ftb.FTB2FTBPlusPOSTagMapper_Impl;
import fr.univnantes.lina.uima.connectors.ftb.FTBPOSTagAnalyser_Impl;

/**
 * XML2CAS TS 2 FTB+ Common TS 
 * 
 * table de conversion (TreeTagger) https://gforge.inria.fr/frs/download.php/1077/Lingua-TagSet-0.3.2.tar.gz
 * table d'alignement Brill/TreeTagger cf. Poulard et al 10
 * 
 * let s prefer the code clarity more than the performance
 * 
 * @author Nicolas Hernandez
 */
public class FTB2FTBPlusAE extends CommonAE {

	/*
	 * LOCAL PARAMETER NAMES 
	 */

	/**
	 * Parameter name of the default value to set when a specified feature has a null value 
	 * If not set, then the value will be 'null' 
	 */
	//public static final String DEFAULT_NULL_VALUE_PARAM = "DefaultNullValue";


	/*
	 * CONFIGURATION PARAMETER NAMES VALUES
	 */
	//public String outputDirForCSVString;

	/**
	 * word annotation type name to create  
	 */
	public String wordAnnotationNameToCreate = "common.types.ext.FTBWord";
	/**
	 * sentence annotation type name to create  
	 */
	public String sentenceAnnotationNameToCreate = "common.types.ext.FTBSentence";


	/*
	 * LOCAL VARIABLES
	 */

	/**
	 *  Default view name if none are specified by the view parameter
	 */
	//private static String DEFAULT_INPUT_VIEW = "_InitialView";

	/**
	 * Name of the default SourceDocumentInformation
	 */
	//private static String DEFAULT_SOURCE_DOCUMENT_INFORMATION_ANNOTATION = "org.apache.uima.examples.SourceDocumentInformation";

	/**
	 * Name of the XML2CAS Element  Annotation
	 */
	private static String XML_ELEMENT_ANNOTATION = "fr.univnantes.lina.uima.connectors.types.XMLElementAnnotation"; //"org.apache.uima.tika.MarkupAnnotation"; 

	/**
	 * Name of the XML2CAS Attribute  Annotation
	 */
	private static String XML_ATTRIBUTE_ANNOTATION = "fr.univnantes.lina.uima.connectors.types.XMLAttributeAnnotation"; 

	/**
	 * 
	 */
	private int numberOfSuccessMapping = 0;
	private int numberOfUnsuccessMapping = 0;

	/**
	 * keys
	 * 
	 */
	private static String begin = "begin";
	private static String end = "end";
	private static String cat = "cat";
	private static String subcat = "subcat";
	private static String mph = "mph";
	private static String lemma = "lemma";
	private static String ftbPlusCat = "ftbpluscat";
	private static String ftbWordTag = "w";
	private static String ftbSentenceTag = "SENT";

	private static String uCatValue = "U"; // undefined or unknown value
	private static String isMultiWords = "isMultiWords";
	private static String isPartOfMultiWords = "isPartOfMultiWords";
	private static String isSimpleWord = "isSimpleWord";
	private static String isGraphicUnit = "isGraphicUnit";
	private static String isRegularForm = "isRegularForm";
	private static String isPartOfAmalgame = "isPartOfAmalgame";
	private static String mood = "mood";	
	private static String tense = "tense";	

	private static String caseF = "case";
	private static String gender = "gender";
	private static String number = "number";
	private static String possNumber = "possNumber";

	/**
	 * Get the values of the configuration parameters
	 * 
	 * @see AnalysisComponent#initialize(UimaContext)
	 */
	public void initialize(UimaContext aContext)
			throws ResourceInitializationException {
		// generic AE parameters
		super.initialize(aContext);

	}


	/**
	 * creates word annotation with the ftb+ tagset
	 * works with the tagged version of the ftb
	 * 
	 * process each XMLElementAnnotation
	 *
	 * several cases
	 * 
	 * 
	 * if SENT create annotation SentenceAnnotation
	 * // compound 
	 * if w and lemma wi ws and numeric pattern create 
	 * // simple w
	 * elsif w and children null and not parent.getQualifiedName.equals(w)
	 * 	if w not open then it may be a simple or a multi
	 * 	else it is a partOf
	 * 	w is open
	 * w end 
	 * 	if  
	 */
	//	@Override
	protected String processInputView(JCas inputViewJCas,
			FSIterator contextAnnotationsFSIter,
			HashMap<String, Integer> inputAnnotationStringHashMap,
			String inputFeatureString, JCas outputViewJCas,
			String outputAnnotationString, String ouputFeatureString)
					throws AnalysisEngineProcessException {

		FSIterator<Annotation> xmlElementAnnotationIterator =  inputViewJCas.getAnnotationIndex(JCasSofaViewUtils.getJCasType(inputViewJCas, XML_ELEMENT_ANNOTATION)).iterator();


		// for processing amalgame
		// initialize future previous created annotation
		Map<String,Object> futureLastWordFeaturesMap = null;

		// Initialize pos mapper and analyzer
		FTB2FTBPlusPOSTagMapper_Impl aFTB2FTBPlusPOSTagMapper = new FTB2FTBPlusPOSTagMapper_Impl();
		FTBPOSTagAnalyser_Impl aFTBPOSTagAnalyser = new FTBPOSTagAnalyser_Impl();

		// For each xml element annotation of the input
		while (xmlElementAnnotationIterator.hasNext()){
			XMLElementAnnotation currentXmlElementAnnotation = (XMLElementAnnotation) xmlElementAnnotationIterator.next();

			// Get the element name
			String currentElementQualifiedName = currentXmlElementAnnotation.getQualifiedName();




			// Process word tags
			if (currentElementQualifiedName.equalsIgnoreCase(ftbWordTag)) {

				// Get word attributes as a map
				Map<String,Object> currentWordFeaturesMap = analyzeXMLElementAnnotation(currentXmlElementAnnotation);

				// algo 1: considering as multi words, only the ftb expressions which can automatically be segmented as it

				// algo 2: considering multi words ftb expression as single tokens "par ailleurs" -> "par_ailleurs"
				//currentWordFeaturesMap.remove(key);

				if (isMultiWords(currentWordFeaturesMap)) {
					// Get the ftb+ pos tag corresponding to the current word
					currentWordFeaturesMap.put(ftbPlusCat, aFTB2FTBPlusPOSTagMapper.mapTag (aFTBPOSTagAnalyser.analyseTag(currentWordFeaturesMap)));
					if (((String)currentWordFeaturesMap.get(ftbPlusCat)).equalsIgnoreCase(uCatValue))numberOfUnsuccessMapping++ ;
					else  numberOfSuccessMapping++;

					// create annotation
					AnnotationUtils.createAnnotation(inputViewJCas, wordAnnotationNameToCreate, currentWordFeaturesMap);
				}
				else if (isSimpleWord(currentWordFeaturesMap)) {
					// if is the part of an amalgame 
					if (isPartOfAmalgame(currentWordFeaturesMap)) {

						// print current word tag
						//System.out.println("Debug: currentWordFeaturesMap"+ currentWordFeaturesMap);

						// get the previous created annotation  
						FSIterator<Annotation> ftbWAnnotationIndextmpIterator =  inputViewJCas.getAnnotationIndex(JCasSofaViewUtils.getJCasType(inputViewJCas, wordAnnotationNameToCreate)).iterator();
						ftbWAnnotationIndextmpIterator.moveToLast();
						// TODO assuming wrongly it always exists one
						common.types.ext.FTBWord  lastFTVWord = (common.types.ext.FTBWord) ftbWAnnotationIndextmpIterator.next() ;

						// print previous word tag created
						//System.out.println("Debug: lastFTVWord"+ lastFTVWord);

						// if the previous created annotation is a prep 
						//<w cat="P" ee="P" ei="P" lemma="à">au</w>
						//<w cat="D" ee="D-def-ms" ei="Dms" lemma="le" mph="ms" subcat="def"/>
						if (lastFTVWord.getCat().equals("P")) {
							// then it has to be corrected

							// modification  ftbpluscat, lemma, subcat, mph
							lastFTVWord.setFtbpluscat(lastFTVWord.getFtbpluscat() + "+" + currentWordFeaturesMap.get(cat));
							lastFTVWord.setLemma(lastFTVWord.getLemma() + " " + currentWordFeaturesMap.get(lemma));
							lastFTVWord.setSubcat(lastFTVWord.getSubcat() +  currentWordFeaturesMap.get(subcat));
							lastFTVWord.setMph(lastFTVWord.getMph() +  currentWordFeaturesMap.get(mph));

							// print previous word tag created after modification
							//System.out.println("Debug: lastFTVWord"+ lastFTVWord);
						}
						// otherwise the next annotation to create has to be corrected
						//<w cat="P" ee="P" ei="P" lemma="à"/>
						//<w cat="PRO" ee="PRO-rel-3mp" ei="PROR3mp" lemma="lequel" mph="3mp" subcat="rel">auxquels</w>
						else {
							futureLastWordFeaturesMap = new HashMap<String, Object>(currentWordFeaturesMap);
						}

					}
					else {
						// it is a simple word which is not part of an amalgame
						// Get the ftb+ pos tag corresponding to the current word
						currentWordFeaturesMap.put(ftbPlusCat, aFTB2FTBPlusPOSTagMapper.mapTag (aFTBPOSTagAnalyser.analyseTag(currentWordFeaturesMap)));
						if (((String)currentWordFeaturesMap.get(ftbPlusCat)).equalsIgnoreCase(uCatValue))numberOfUnsuccessMapping++ ;
						else  numberOfSuccessMapping++;

						// if the previous word tag was part of an amalgame 
						if (futureLastWordFeaturesMap != null) {
							// correct the current word before creation
							currentWordFeaturesMap.put(ftbPlusCat, 	futureLastWordFeaturesMap.get(cat) + "+" + currentWordFeaturesMap.get(cat));
							currentWordFeaturesMap.put(lemma, 	futureLastWordFeaturesMap.get(lemma) + " " + currentWordFeaturesMap.get(lemma));
							currentWordFeaturesMap.put(subcat, 	futureLastWordFeaturesMap.get(subcat) + "" +  currentWordFeaturesMap.get(subcat));
							currentWordFeaturesMap.put(mph, 	futureLastWordFeaturesMap.get(mph) + "" +  currentWordFeaturesMap.get(mph));

							// re init
							futureLastWordFeaturesMap = null;
						}
						// create annotation
						AnnotationUtils.createAnnotation(inputViewJCas, wordAnnotationNameToCreate, currentWordFeaturesMap);

					}
				}


				// do not process the part of multi words


				// for correcting amalgame keep the track of the current and future previous created annotation




				//
				/*
				System.out.println("Debug: coveredText>"+currentXmlElementAnnotation.getCoveredText()
								+"< cat>"+currentWordFeaturesMap.get(cat)
								+"< subcat>"+currentWordFeaturesMap.get(subcat)
								+"< isSimpleWord>" + String.valueOf(isSimpleWord(currentWordFeaturesMap))
								+"< isMultiWords>" + String.valueOf(isMultiWords(currentWordFeaturesMap))
								+"< isPartOf>" + String.valueOf(isPartOfMultiWords(currentWordFeaturesMap))
								+"< isGraphicUnit>"+ String.valueOf(isGraphicUnit(currentWordFeaturesMap))
								+"< isRegularForm>" + String.valueOf(isRegularForm(currentWordFeaturesMap))
								+"< isSecondPartOfAmalgame>" + String.valueOf(isSecondPartOfAmalgame(currentWordFeaturesMap)) 

								+"<" );
				 */


			}
			else		// Create FTBSentence annotation 
				if (currentElementQualifiedName.equalsIgnoreCase(ftbSentenceTag)) {
					//System.out.println ("Warning: "+currentXmlElementAnnotation.getCoveredText());
					Map<String,Object> currentSentenceFeaturesMap = new HashMap<String, Object>();
					currentSentenceFeaturesMap.put(begin, String.valueOf(currentXmlElementAnnotation.getBegin()));
					currentSentenceFeaturesMap.put(end, String.valueOf(currentXmlElementAnnotation.getEnd()));
					AnnotationUtils.createAnnotation(inputViewJCas, sentenceAnnotationNameToCreate, currentSentenceFeaturesMap);

				}

		}

		// La méthode requiert de retourner quelque chose 
		// Le plus simple est de lui retourner l'image d'elle même
		return inputViewJCas.getDocumentText();
	}

	/**
	 * XMLElementAnnotation (e.g. AttributesArray) to Map 
	 */
	public Map<String, Object> analyzeXMLElementAnnotation(XMLElementAnnotation currentXmlElementAnnotation) {
		Map<String,Object> currentWordMorphoSyntaxFeaturesMap = new HashMap<String, Object>();
		// Get the attribute name and values of 
		// In particular for cat/catint subcat mph

		currentWordMorphoSyntaxFeaturesMap.put(cat, "");
		currentWordMorphoSyntaxFeaturesMap.put(subcat, "");
		currentWordMorphoSyntaxFeaturesMap.put(mph, "");
		currentWordMorphoSyntaxFeaturesMap.put(lemma, "");
		currentWordMorphoSyntaxFeaturesMap.put(mood, "");
		currentWordMorphoSyntaxFeaturesMap.put(tense, "");

		currentWordMorphoSyntaxFeaturesMap.put(caseF, "");
		currentWordMorphoSyntaxFeaturesMap.put(gender, "");
		currentWordMorphoSyntaxFeaturesMap.put(number, "");
		currentWordMorphoSyntaxFeaturesMap.put(possNumber, "");

		currentWordMorphoSyntaxFeaturesMap.put(isPartOfMultiWords, "");
		currentWordMorphoSyntaxFeaturesMap.put(isGraphicUnit, "");
		currentWordMorphoSyntaxFeaturesMap.put(isRegularForm, "");
		currentWordMorphoSyntaxFeaturesMap.put(isPartOfAmalgame, "");

		currentWordMorphoSyntaxFeaturesMap.put(begin, String.valueOf(currentXmlElementAnnotation.getBegin()));
		currentWordMorphoSyntaxFeaturesMap.put(end, String.valueOf(currentXmlElementAnnotation.getEnd()));


		// is multiWords
		currentWordMorphoSyntaxFeaturesMap.put(isMultiWords, String.valueOf(isMultiWords(currentXmlElementAnnotation)));

		// is part of
		currentWordMorphoSyntaxFeaturesMap.put(isPartOfMultiWords, String.valueOf(isPartOfMultiWords(currentXmlElementAnnotation)));

		// is simpleWord
		currentWordMorphoSyntaxFeaturesMap.put(isSimpleWord, String.valueOf(isSimpleWord(currentXmlElementAnnotation)));

		// is graphical Unit
		currentWordMorphoSyntaxFeaturesMap.put(isGraphicUnit, String.valueOf(isGraphicUnit(currentXmlElementAnnotation)));

		// is regular form
		currentWordMorphoSyntaxFeaturesMap.put(isRegularForm, String.valueOf(isRegularForm(currentXmlElementAnnotation)));

		// is second part of amalgame
		currentWordMorphoSyntaxFeaturesMap.put(isPartOfAmalgame, String.valueOf(isPartOfAmalgame(currentXmlElementAnnotation)));


		//
		for (int i = 0; i < currentXmlElementAnnotation.getAttributes().size(); i++) {
			XMLAttributeAnnotation currentXmlAttributeAnnotation = currentXmlElementAnnotation.getAttributes(i);
			String currentAttributeQualifiedName = currentXmlAttributeAnnotation.getQualifiedName();
			String currentAttributeValue = currentXmlAttributeAnnotation.getValue();
			// embedded words will also be described by cat feature
			if (currentAttributeQualifiedName.equalsIgnoreCase(cat) || currentAttributeQualifiedName.equalsIgnoreCase("catint")) {
				currentWordMorphoSyntaxFeaturesMap.put(cat, currentAttributeValue);
			}
			// subcat
			else if (currentAttributeQualifiedName.equalsIgnoreCase(subcat)) {
				currentWordMorphoSyntaxFeaturesMap.put(subcat, currentAttributeValue);
			}
			//mph
			else if (currentAttributeQualifiedName.equalsIgnoreCase(mph)) {
				currentWordMorphoSyntaxFeaturesMap.put(mph, currentAttributeValue);

			}
			// lemma
			else if (currentAttributeQualifiedName.equalsIgnoreCase(lemma)) {
				currentWordMorphoSyntaxFeaturesMap.put(lemma, currentAttributeValue);
			}

		} 
		//System.out.println("Debug: eqn "+currentElementQualifiedName+" cat "+cat+" subcat "+subcat+" mph "+mph);
		return currentWordMorphoSyntaxFeaturesMap;

	}

	/**
	 * get the attribute value corresponding to a given attribute name
	 */
	public String getAttributeValue(XMLElementAnnotation currentXmlElementAnnotation, String name) {
		int i = 0;
		Boolean found = false ;
		String result = "" ; //null; empty string correspond to no value !
		while (i < currentXmlElementAnnotation.getAttributes().size() && !found) {
			XMLAttributeAnnotation currentXmlAttributeAnnotation = currentXmlElementAnnotation.getAttributes(i);
			String currentAttributeQualifiedName = currentXmlAttributeAnnotation.getQualifiedName();

			if (currentAttributeQualifiedName.equalsIgnoreCase(name)) {
				found = true;
				result = currentXmlAttributeAnnotation.getValue();
			}
			i++;
		}
		return result;
	}


	/**
	 * is the word a compound / a multi-words expression currentXmlElementAnnotation
	 */
	public Boolean isMultiWords (XMLElementAnnotation currentXmlElementAnnotation) {
		return currentXmlElementAnnotation.getChildren().size() != 0;
	}

	/**
	 * is the word a compound / a multi-words expression currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isMultiWords (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		return Boolean.valueOf((String)currentWordMorphoSyntaxFeaturesMap.get(isMultiWords));
	}


	/**
	 * is part of a multi words expressions currentXmlElementAnnotation
	 */
	public Boolean isPartOfMultiWords (XMLElementAnnotation currentXmlElementAnnotation) {
		return isMultiWords(currentXmlElementAnnotation.getParent()) && 
				currentXmlElementAnnotation.getParent().getQualifiedName().equalsIgnoreCase(ftbWordTag);
	}

	/**
	 * is part of a multi words expressions currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isPartOfMultiWords (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		return Boolean.valueOf((String)currentWordMorphoSyntaxFeaturesMap.get(isPartOfMultiWords));

	}

	/**
	 * is a simple word (not part of a multi)  currentXmlElementAnnotation
	 */
	public Boolean isSimpleWord (XMLElementAnnotation currentXmlElementAnnotation) {
		return !isPartOfMultiWords(currentXmlElementAnnotation) && !isMultiWords(currentXmlElementAnnotation);
	}

	/**
	 * is a simple word (not part of a multi) currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isSimpleWord (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		return Boolean.valueOf((String)currentWordMorphoSyntaxFeaturesMap.get(isSimpleWord));

	}

	/**
	 * is the word a graphic unit currentXmlElementAnnotation
	 */
	public Boolean isGraphicUnit (XMLElementAnnotation currentXmlElementAnnotation) {
		return getAttributeValue(currentXmlElementAnnotation,lemma).trim().indexOf(" ") == -1;
	}

	/**
	 * is the word a graphic unit currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isGraphicUnit (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		return Boolean.valueOf((String)currentWordMorphoSyntaxFeaturesMap.get(isGraphicUnit));

	}


	/**
	 * is a regular form currentXmlElementAnnotation currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isRegularForm (XMLElementAnnotation currentXmlElementAnnotation) {

		// numberString and number , ordinal String too
		String numberPattern = "^(\\d+|une?|deux|trois|quatre|cinq|six|sept|huit|neuf|z(e|é)ro|dix|onze|douze|treize|quatorze|quinze|seize|vingts?|trentes?|quarantes?|cinquantes?|soixantes?|septentes?|huitantes?|nonentes?|cents?|milles?)((-|et|sur|,|\\.| )(\\d+|une?|deux|trois|quatre|cinq|six|sept|huit|neuf|z(e|é)ro|dix|onze|douze|treize|quatorze|quinze|seize|vingts?|trentes?|quarantes?|cinquantes?|soixantes?|septentes?|huitantes?|nonentes?|cents?|milles?|milliers?|millions?|milliards?|billions?|billiards?|trillions?|trilliards?|quadrilliards?|demi|tiers|quart|uni(è|e)me|deuxi(è|e)me|troisi(è|e)me|quatri(è|e)me|cinqui(è|e)me|sixi(è|e)me|septi(è|e)me|huiti(è|e)me|neuvi(è|e)me|dixi(è|e)me|vingti(è|e)me|trentri(è|e)me|quaranti(è|e)me|cinquanti(è|e)me|soixanti(è|e)me|septenti(è|e)me|huitanti(è|e)me|nonenti(è|e)me|onzi(è|e)me|douzi(è|e)me|treizi(è|e)me|quatorzi(è|e)me|quinzi(è|e)me|seizi(è|e)me|dix-septi(è|e)me|dix-huiti(è|e)me|dix-neuvi(è|e)me|centi(è|e)me|milli(è|e)me|millioni(è|e)me|milliardi(è|e)me))*$";
		// number
		//"^\\d+( \\d+)*(,\\d+)?$"
		Pattern pattern = Pattern.compile(numberPattern, Pattern.CASE_INSENSITIVE);
		// In case you would like to ignore case sensitivity you could use this
		// statement
		// Pattern pattern = Pattern.compile("\\s+", Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(getAttributeValue(currentXmlElementAnnotation,lemma).trim());
		// Check 
		if (matcher.find()) return true;
		return false;	
	}

	/**
	 * is a regular form currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isRegularForm (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		return Boolean.valueOf((String)currentWordMorphoSyntaxFeaturesMap.get(isRegularForm));
	}


	/**
	 * belongs to a dictionary (list of multi words adverbs or preposition as UIMA resources) currentXmlElementAnnotation
	 * 
	 */
	public Boolean isDictionaryStableForm (XMLElementAnnotation currentXmlElementAnnotation) {
		//TODO
		return false;
	}

	/**
	 * belongs to a dictionary (list of multi words adverbs or preposition as UIMA resources) currentWordMorphoSyntaxFeaturesMap
	 * 
	 */
	public Boolean isDictionaryStableForm (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		//TODO
		return false;
	}

	/**
	 * is it an automatic segmented token currentXmlElementAnnotation
	 * 
	 */
	public Boolean isAutomaticSegmentedToken (XMLElementAnnotation currentXmlElementAnnotation) {
		return isGraphicUnit(currentXmlElementAnnotation) || isRegularForm (currentXmlElementAnnotation) || isDictionaryStableForm(currentXmlElementAnnotation);
	}	

	/**
	 * is the part of an amalgame (e.g. du, au) currentXmlElementAnnotation
	 * 
	<w cat="P" ee="P" ei="P" lemma="à"/>
	<w cat="PRO" ee="PRO-rel-3mp" ei="PROR3mp" lemma="lequel" mph="3mp" subcat="rel">auxquels</w>

    <w cat="P" ee="P" ei="P" lemma="à">au</w>
    <w cat="D" ee="D-def-ms" ei="Dms" lemma="le" mph="ms" subcat="def"/>

	 */
	public Boolean isPartOfAmalgame (XMLElementAnnotation currentXmlElementAnnotation) {
		return currentXmlElementAnnotation.getCoveredText().trim().equalsIgnoreCase("");
	}

	/**
	 * is the second part of an amalgame (e.g. du, au) currentWordMorphoSyntaxFeaturesMap
	 */
	public Boolean isPartOfAmalgame  (Map<String,Object> currentWordMorphoSyntaxFeaturesMap) {
		return Boolean.valueOf((String)currentWordMorphoSyntaxFeaturesMap.get(isPartOfAmalgame));
	}


	/**
	 * display some stat
	 */
	@Override
	public void collectionProcessComplete() {
		System.err.println("INFO: # FTB 2 FTB+ Mapping " + (numberOfSuccessMapping +numberOfUnsuccessMapping));
		System.err.println("INFO: # FTB 2 FTB+ Mapping success " + numberOfSuccessMapping);
		System.err.println("INFO: # FTB 2 FTB+ Mapping unsuccess " + numberOfUnsuccessMapping);
	}

}